#include "game_byte.h"
#include <stdlib.h>
#include <string.h>
#include "game_macros.h"



CGameByteRing::CGameByteRing(UINT32 capacity){
  _capacity = capacity;

  _buf = (BYTE*)malloc(capacity);

  reset();
}

CGameByteRing::~CGameByteRing(){
  free(_buf);
}

void CGameByteRing::reset(){

  _read = 0;
  _write = 0;
  memset(_buf,0,_capacity);
}

UINT32 CGameByteRing::getCapacity()
{
  return _capacity;
}


BOOL CGameByteRing::write(const BYTE* src,const UINT32 len){



  do{
    UINT32 can = writeAvailable();
    // CC_BREAK_IF_WAR(len > can,logger,"%s","overrun")


    UINT32 w = _write + len;

    const void* ptr;
    void* d;

    if(w > _capacity){
      d = _buf +  _write;
      //第一次写入
      int cpy = _capacity - _write;
      ptr = src;
      memcpy(d,ptr,cpy);

      //第二次写入
      d = _buf;
      ptr = src + cpy;
      cpy = w - _capacity;
      memcpy(d,ptr,cpy);
      w = cpy;
    }else{
      d = _buf + _write;
      ptr = src;
      memcpy(d,ptr,len );
      if(w == _capacity)
        w = 0;
    }

    // logger->trace("write[%d] at %d,next is %d",len,_write,w);
    _write = w;
    // _count = 1;
    return TRUE;
  }while(true);


  return FALSE;
}

UINT32 CGameByteRing::writeAvailable(){
  if(_write == _read)
    return _capacity;

  if(_write < _read)
    return _read - _write;
  else if(_write > _read){
    return _read + (_capacity - _write);
  }else return 0;
}

UINT32 CGameByteRing::readAvailable(){
  if(_read == _write)
    return 0;


  if(_write < _read)
    return _capacity - _read + _write;
  else return _write - _read;
}

BOOL CGameByteRing::read(BYTE* dest,const UINT32 len){



  do{
    UINT32 has = readAvailable();
    // CC_BREAK_IF_WAR(len > has,logger,"%s","underrun")
    UINT32 r = _read + len;
    void* ptr;
    void* d;
    if(r > _capacity){
      ptr = _buf + _read;
      //第一次写入
      int cpy = _capacity - _read;
      d = dest;
      memcpy(d,ptr,cpy);

      //第二次写入
      d = dest + cpy;
      cpy = r - _capacity;
      ptr = _buf;
      memcpy(d,ptr,cpy);

      r = cpy;
    }else{
      ptr = _buf + _read;
      memcpy(dest,ptr,len);

      if(r == _capacity)
        r = 0;
    }




    // logger->debug("read[%d] at %d,next is %d",len,_read,r);
    _read = r;
    return TRUE;
  }while(true);

  return FALSE;
}
